import { RuleParse } from "../type";
import escapeRuleParse from './escapeRuleParse';
import globelRuleParse from "./globelRuleParse";

const rangeRuleParse: RuleParse = {

	parseType: "range",

	isNested: false,

	preHandle: (parse, rule, char) => {
		const parseType = parse.top && parse.top.parseType;
		const ruleSt = rule.select;
		if (parseType === "range" && ruleSt !== undefined && ruleSt.children.length > 0) {
			const startCode = <number>ruleSt.info.ruleData;
			const endCode = <number>ruleSt.children[0].info.ruleData;
			if (startCode > endCode) {
				throw new Error("字符区间起始字符不能大于结束字符");
			}
			ruleSt.info.ruleType = "range";
			ruleSt.info.ruleData = (save, origin, rule, str, index, char, length) => {
				const code = char.charCodeAt(0);
				return code >= startCode && code <= endCode;
			};
			rule.back();
			parse.pop();
		} else if (parseType === "globel" && char === "-") {
			if (parseType !== "globel") {
				throw new Error("字符区间书写位置错误");
			} else if (ruleSt === undefined) {
				throw new Error("字符区间无起始字符");
			} else if (ruleSt.info.ruleType !== "equals") {
				throw new Error("字符区间无法作用与非字符项");
			}
			parse.pop();
			parse.push(rangeRuleParse);
		}
	},

	judge: (parse, rule, char) => {
		return false;
	},

	// [canNested=true]
	handle: (parse, rule, char) => {
		const parseType = parse.top && parse.top.parseType;
		const ruleSt = rule.select;
		if (parseType === "range") {
			if (ruleSt === undefined) {
				throw new Error("栈列表选项为空");
			}
			if (char === "-" && ruleSt.children.length === 0) {
				return false;
			}
			if (ruleSt.children.length === 0 && char === "\\") {
				parse.push(escapeRuleParse);
			} else {
				const startCode = <number>ruleSt.info.ruleData;
				const endCode = char.charCodeAt(0);
				if (startCode > endCode) {
					throw new Error("字符区间起始字符不能大于结束字符");
				}
				ruleSt.info.ruleType = "range";
				ruleSt.info.ruleData = (save, origin, rule, str, index, char, length) => {
					const code = char.charCodeAt(0);
					return code >= startCode && code <= endCode;
				};
				parse.pop();
				parse.push(globelRuleParse);
			}
			return true;
		}
		return false;
	},
};

export default rangeRuleParse;
